home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / comm1 / s2mtr376.lha / SANA2Meter / Source / sana2meter.c < prev    next >
C/C++ Source or Header  |  1996-04-27  |  44KB  |  1,382 lines

  1. /*
  2. ** $VER: sana2meter.c 1.5 (25 Apr 1996)
  3. **
  4. ** (C) Copyright 1996 Marius Gröger
  5. **     All Rights Reserved
  6. **
  7. ** $HISTORY:
  8. **
  9. ** 25 Apr 1996 : 001.005 :  some parts moved to support.c, sana2meter.h
  10. ** 20 Apr 1996 : 001.004 :  support for multiple devices
  11. ** 15 Apr 1996 : 001.003 :  support for broken gadtools V39
  12. ** 14 Apr 1996 : 001.002 :  failing DoIO()'s will turn off further displaying
  13. **                          of the corresponding values
  14. ** 10 Apr 1996 : 001.001 :  packet type tracking
  15. ** 26 Mar 1996 : 001.000 :  created
  16. */
  17.  
  18. #define DEBUG 0
  19. #define USE_EXTREADARGS 1
  20. #define CATALOG_VERSION 3
  21.  
  22. /*F*/ /* includes */
  23.  
  24. #include <clib/alib_protos.h>
  25. #include <clib/dos_protos.h>
  26. #include <pragmas/dos_pragmas.h>
  27. #include <clib/utility_protos.h>
  28. #include <pragmas/utility_pragmas.h>
  29. #include <clib/exec_protos.h>
  30. #include <pragmas/exec_sysbase_pragmas.h>
  31. #include <clib/intuition_protos.h>
  32. #include <pragmas/intuition_pragmas.h>
  33. #include <clib/gadtools_protos.h>
  34. #include <pragmas/gadtools_pragmas.h>
  35. #include <clib/icon_protos.h>
  36. #include <pragmas/icon_pragmas.h>
  37. #include <clib/locale_protos.h>
  38. #include <pragmas/locale_pragmas.h>
  39. #include <gtlayout/gtlayout.h>
  40. #include <exec/libraries.h>
  41. #include <exec/devices.h>
  42. #include <exec/memory.h>
  43. #include <exec/io.h>
  44. #include <workbench/startup.h>
  45. #include <utility/tagitem.h>
  46. #include <netinclude:devices/sana2.h>
  47. #define AsmPools
  48. #include <pools/pool_lib.h>
  49.  
  50. #if (USE_EXTREADARGS != 0)
  51. #include <extrdargs.h>
  52. #endif
  53.  
  54. #include "compiler.h"
  55. #include "debug.h"
  56. #define CATCOMP_NUMBERS
  57. #include "locale.h"
  58. #include "sana2meter.h"
  59. #include "constdata.h"
  60.  
  61. #include <strings.h>
  62. #include <stddef.h>
  63. /*E*/
  64.  
  65. /*F*/ /* private symbols */
  66. PRIVATE BOOL parseargs(GD gd);
  67. PRIVATE VOID cleanup(GD gd);
  68. PRIVATE BOOL opendevs(GD gd);
  69. PRIVATE GD createenv(ULONG argc, UBYTE **argv);
  70. PRIVATE VOID getspeciallabels(GD gd);
  71. PRIVATE struct GlobalDevData *makedevice(GD gd, STRPTR devicename);
  72. PRIVATE VOID dummys2copy(VOID);
  73. /*E*/
  74. /*F*/ /* exported symbols */
  75. PUBLIC VOID SAVEDS STDARGS main(ULONG argc, UBYTE **argv);
  76. PUBLIC VOID saveconfig(GD gd);
  77. PUBLIC VOID updateupdate(GD gd, struct GlobalDevData *gdd);
  78. PUBLIC UWORD updateglobalstats(GD gd, struct GlobalDevData *gdd);
  79. PUBLIC UWORD updatespecialstats(GD gd, struct GlobalDevData *gdd);
  80. PUBLIC UWORD updatetracktype(GD gd, struct GlobalDevData *gdd);
  81. PUBLIC VOID updateactives(GD gd);
  82. /*E*/
  83. /*F*/ /* imported symbols */
  84. IMPORT struct Library *openlib(GD gd, STRPTR name, LONG version);
  85. IMPORT STDARGS STRPTR GetString(struct LocaleInfo *li, LONG stringNum);
  86. IMPORT STDARGS VOID exit(LONG);
  87. IMPORT STDARGS VOID sprintf(char *, char *, ...);
  88. IMPORT VOID message(GD gd, LONG, LONG, LONG, ...);
  89. IMPORT VOID *allocpvec(GD gd, ULONG len);
  90. IMPORT VOID freepvec(GD gd, VOID *mem);
  91. IMPORT VOID *allocppvec(GD gd, ULONG len);
  92. IMPORT VOID freeppvec(GD gd, VOID *mem);
  93. IMPORT BOOL preparemenu(GD gd);
  94. IMPORT BOOL dowindow(GD gd, BOOL *update);
  95. IMPORT VOID checkmenu(GD gd);
  96. IMPORT VOID updategui(GD gd, BOOL complete);
  97. IMPORT VOID closegui(GD gd);
  98. IMPORT BOOL opengui(GD gd);
  99. IMPORT ULONG strntolong(GD gd, STRPTR s, LONG *number, LONG n);
  100. IMPORT char *AddToolType(GD gd, struct DiskObject *dobj, char *tool);
  101. /*E*/
  102.  
  103. /*F*/ /* constants for parsing */
  104. PRIVATE const UBYTE TEMPLATE[] = "DEV=DEVICE,"            \
  105.                                  "U=UNIT/K/N,"            \
  106.                                  "S=SHOW/K,"              \
  107.                                  "TT=TRACKTYPE/K,"        \
  108.                                  "FORCE/S,"               \
  109.                                  "OFF/S,"                 \
  110.                                  "FROM/K,"                \
  111.                                  "RF=REFRESH/K/N,"        \
  112.                                  "L=LIST/S,"              \
  113.                                  "FONT=FONTNAME/K,"       \
  114.                                  "FONTSIZE/K/N,"          \
  115.                                  "TOP/K/N,"               \
  116.                                  "LEFT/K/N,"              \
  117.                                  "SCREEN=PUBSCREEN/K,"    \
  118.                                  "NA=NOACTIVATE/S,"       \
  119.                                  "W2B=WINDOWTOBACK/S,"    \
  120.                                  "WINDOW/K";
  121.  
  122. enum
  123. {
  124.    ARG_DEVICE,
  125.    ARG_UNIT,
  126.    ARG_SHOW,
  127.    ARG_TRACKTYPE,
  128.    ARG_FORCE,
  129.    ARG_OFF,
  130.    ARG_FROM,
  131.    ARG_REFRESH,
  132.    ARG_LIST,
  133.    ARG_FONT,
  134.    ARG_FONTSIZE,
  135.    ARG_TOP,
  136.    ARG_LEFT,
  137.    ARG_PUBSCREEN,
  138.    ARG_NOACTIVATE,
  139.    ARG_WINDOWTOBACK,
  140.    ARG_WINDOW,
  141.    ARG_COUNT
  142. };
  143.  
  144.  
  145. #define DEF_UNIT 0
  146. #define DEF_REFRESH 2
  147. #define DEF_FONTSIZE 8
  148. #define DEF_LEFT 30
  149. #define DEF_TOP 20
  150.  
  151. PRIVATE UBYTE KEYDELIMITERS[]   = ",;| ";
  152. PRIVATE UBYTE TTMASKSEPARATOR[] = ":/";
  153. PRIVATE UBYTE TTMASKACTIVE[]    = "+xX#";
  154. PRIVATE UBYTE TTMASKINACTIVE[]  = "-oO.";
  155.  
  156. /*E*/
  157.  
  158. /*F*/ PRIVATE struct GlobalDevData *makedevice(GD gd, STRPTR devicename)
  159. {
  160.    const struct NewWatch * nw;
  161.    struct Watch *w;
  162.    struct Sana2SpecialStatRecord *sr;
  163.    struct GlobalDevData *gdd;
  164.    struct PublicDevData *pdd;
  165.    BOOL rc = FALSE;
  166.  
  167.    if (gdd = allocpvec(gd, sizeof(struct GlobalDevData) + strlen(devicename)))
  168.    {
  169.       strcpy((char*)gdd->gd_Device, devicename);
  170.       gdd->gd_Unit = DEF_UNIT;
  171.       gdd->gd_Active = 1;
  172.       NewList((struct List*)&gdd->gd_Watches);
  173.  
  174.       if (pdd = gdd->gd_Public = allocppvec(gd, sizeof(struct PublicDevData)))
  175.       {
  176.          sr = pdd->pd_S2SpecialStatRecs;
  177.  
  178.          rc = TRUE;
  179.  
  180.          if (gdd->gd_StdWatches = allocpvec(gd, (NUM_SPECIALSTATS+NUM_STDWATCHES)*sizeof(struct Watch)))
  181.          {
  182.             /* create all the watches from the NewWatch array */
  183.             for (w = gdd->gd_StdWatches, nw = stdwatches; nw->nw_Member != MEMBER_NONE; ++nw, ++w)
  184.             {
  185.                w->w_Member = nw->nw_Member;
  186.                w->w_Key = nw->nw_Key;
  187.                w->w_ShortKey = nw->nw_ShortKey;
  188.                if (!(nw->nw_Flags & WF_NOLABEL))
  189.                   w->w_Label = GetString(&gd->gd_LocaleInfo, nw->nw_LabelID);
  190.                w->w_Flags = nw->nw_Flags;
  191.  
  192.                if (nw->nw_Member == MEMBER_GLOBALSTATS)
  193.                   w->w_Value = (ULONG*)((UBYTE*)&pdd->pd_S2DeviceStats + nw->nw_StructOffset);
  194.                else if (nw->nw_Member == MEMBER_DEVICEQUERY)
  195.                   w->w_Value = (ULONG*)((UBYTE*)&pdd->pd_S2DeviceQuery + nw->nw_StructOffset);
  196.                else if (nw->nw_Member == MEMBER_SPECIALSTATS)
  197.                {
  198.                   w->w_Value = &sr->Count;
  199.                   ++sr;
  200.                }
  201.                else
  202.                   w->w_Value = NULL;
  203.  
  204.                AddTail((struct List*)&gdd->gd_Watches, (struct Node*)&w->w_Link);
  205.             }
  206.          } else rc = FALSE;
  207.       }
  208.  
  209.       if (!rc)
  210.       {
  211.          if (gdd->gd_StdWatches) freepvec(gd, gdd->gd_StdWatches);
  212.          if (gdd->gd_Public) freepvec(gd, gdd->gd_Public);
  213.          freepvec(gd, gdd);
  214.          gdd = NULL;
  215.       }
  216.    }
  217.  
  218.    return gdd;
  219. }
  220. /*E*/
  221. /*F*/ PRIVATE BOOL preparetts(GD gd)
  222. {
  223.    struct NewWatch *nw;
  224.    struct TrackType *tt;
  225.    struct Watch *w;
  226.    BOOL rc = TRUE, first;
  227.    ULONG numtt, i;
  228.    struct GlobalDevData *gdd;
  229.    struct PublicDevData *pdd;
  230.  
  231.    SCANDEVS(gdd, &gd->gd_Devices)
  232.    {
  233.       pdd = gdd->gd_Public;
  234.       if (gdd->gd_TrackWatches = allocpvec(gd, NUM_TTWATCHES*gdd->gd_NumTT*sizeof(struct Watch)))
  235.       {
  236.          w = gdd->gd_TrackWatches;
  237.          for (tt=pdd->pd_TrackedTypes, numtt = gdd->gd_NumTT; numtt; ++tt,  --numtt)
  238.          {
  239.             for (i=0, first=TRUE, nw=(struct NewWatch *)ttwatches; nw->nw_Member != MEMBER_NONE;
  240.                                                                         ++i, ++nw, first=FALSE)
  241.             {
  242.                w->w_Member = nw->nw_Member;
  243.                w->w_TrackType = tt;
  244.                w->w_Key = first ? tt->tt_Key : NULL;
  245.                w->w_Label = GetString(&gd->gd_LocaleInfo, nw->nw_LabelID);
  246.                w->w_Flags = nw->nw_Flags | (first ? WF_FIRSTTT : 0);
  247.                if (tt->tt_Flags & TTF_INITIAL_SETUP)
  248.                {
  249.                   if (tt->tt_Flags & ttmaskflags[i])
  250.                      w->w_Flags |= WF_ACTIVE;
  251.                   else
  252.                      w->w_Flags &= ~WF_ACTIVE;
  253.                }
  254.                w->w_Value = (ULONG*)((UBYTE*)&tt->tt_Stats + nw->nw_StructOffset);
  255.                AddTail((struct List*)&gdd->gd_Watches, (struct Node*)&w->w_Link);
  256.  
  257.                ++w;
  258.             }
  259.          }
  260.       }
  261.    }
  262.    return rc;
  263. }
  264. /*E*/
  265. /*F*/ PRIVATE VOID getspeciallabels(GD gd)
  266. {
  267.    struct Watch *w;
  268.    BOOL specials;
  269.    struct GlobalDevData *gdd;
  270.    struct PublicDevData *pdd;
  271.  
  272.    SCANDEVS(gdd, &gd->gd_Devices)
  273.    {
  274.       pdd = gdd->gd_Public;
  275.       specials = FALSE;
  276.  
  277.       gdd->gd_ValidSpecialStats = 0;
  278.  
  279.       SCANWATCHES(w, &gdd->gd_Watches)
  280.       {
  281.          if (!specials)
  282.          {
  283.             if (w->w_Member == MEMBER_SPECIALSTATS)
  284.                specials = TRUE;
  285.          }
  286.          if (specials)
  287.          {
  288.             if ((gdd->gd_ValidSpecialStats >= NUM_SPECIALSTATS) ||
  289.                               !(pdd->pd_S2SpecialStatRecs[gdd->gd_ValidSpecialStats].String))
  290.                break;
  291.             w->w_Label = pdd->pd_S2SpecialStatRecs[gdd->gd_ValidSpecialStats].String;
  292.             ++gdd->gd_ValidSpecialStats;
  293.          }
  294.       }
  295.    }
  296.  
  297.    return ;
  298. }
  299. /*E*/
  300.  
  301. /*F*/ PUBLIC VOID updateactives(GD gd)
  302. {
  303.    struct GlobalDevData *gdd;
  304.  
  305.    gd->gd_NeedTimer = 0;
  306.    gd->gd_NumActives = 0;
  307.    SCANDEVS(gdd, &gd->gd_Devices)
  308.    {
  309.       d(("device <%s>\n", gdd->gd_Device));
  310.  
  311.       if (!gdd->gd_GetGlobalStats && !gdd->gd_GetSpecialStats &&
  312.            !gdd->gd_GetTrackType && !gdd->gd_ShowDevQuery)
  313.          gdd->gd_Active = 0;
  314.       else
  315.       {
  316.          if (gdd->gd_Active)
  317.          {
  318.             if (gdd->gd_GetGlobalStats || gdd->gd_GetSpecialStats || gdd->gd_GetTrackType)
  319.                gd->gd_NeedTimer = 1;
  320.  
  321.             ++gd->gd_NumActives;
  322.          }
  323.       }
  324.       d(("GetGlobalStats %ld, GetSpecialStats %ld, GetTrackType %ld, Active %ld\n",
  325.          gdd->gd_GetGlobalStats, gdd->gd_GetSpecialStats, gdd->gd_GetTrackType, gdd->gd_Active));
  326.  
  327.    }
  328.    d(("NeedTimer %ld, NumActives %ld\n", gd->gd_NeedTimer, gd->gd_NumActives));
  329. }
  330. /*E*/
  331. /*F*/ PUBLIC VOID updateupdate(GD gd, struct GlobalDevData *gdd)
  332. {
  333.    struct Watch *w;
  334.    struct TrackType *tt;
  335.    ULONG i;
  336.    struct PublicDevData *pdd;
  337.  
  338.    pdd = gdd->gd_Public;
  339.  
  340.    gdd->gd_GetGlobalStats = 0;
  341.    gdd->gd_GetSpecialStats = 0;
  342.    gdd->gd_GetTrackType = 0;
  343.    gdd->gd_ShowDevQuery = 0;
  344.  
  345.    for(i=gdd->gd_NumTT, tt=pdd->pd_TrackedTypes; i; --i, ++tt)
  346.       tt->tt_Flags &= ~TTF_ACTIVE;
  347.  
  348.    SCANWATCHES(w, &gdd->gd_Watches)
  349.    {
  350.       if ((w->w_Flags & WF_ACTIVE) && (w->w_Member == MEMBER_DEVICEQUERY))
  351.          gdd->gd_ShowDevQuery = 1;
  352.  
  353.       if ((w->w_Flags & WF_ACTIVE) && (w->w_Member == MEMBER_GLOBALSTATS))
  354.          gdd->gd_GetGlobalStats = 1;
  355.  
  356.       if ((w->w_Flags & WF_ACTIVE) && (w->w_Member == MEMBER_SPECIALSTATS))
  357.          gdd->gd_GetSpecialStats = 1;
  358.  
  359.       if (w->w_Member == MEMBER_TRACKTYPE)
  360.       {
  361.          if (w->w_Flags & WF_ACTIVE)
  362.          {
  363.             w->w_TrackType->tt_Flags |= TTF_ACTIVE;
  364.             gdd->gd_GetTrackType = 1;
  365.          }
  366.       }
  367.    }
  368.    return ;
  369. }
  370. /*E*/
  371. /*F*/ PUBLIC UWORD updateglobalstats(GD gd, struct GlobalDevData *gdd)
  372. {
  373.    struct PublicDevData *pdd;
  374.    UWORD rc = 0;
  375.  
  376.    pdd = gdd->gd_Public;
  377.    pdd->pd_S2Req.ios2_StatData = (void*)&pdd->pd_S2DeviceStats;
  378.    pdd->pd_S2Req.ios2_Req.io_Command = S2_GETGLOBALSTATS;
  379.    if (DoIO((struct IORequest*)&pdd->pd_S2Req))
  380.    {
  381.       struct Watch *w;
  382.  
  383.       SCANWATCHES(w, &gdd->gd_Watches)
  384.       {
  385.          if (w->w_Member == MEMBER_GLOBALSTATS)
  386.             w->w_Flags = (w->w_Flags & ~WF_ACTIVE) | WF_OFF;
  387.       }
  388.       rc = 1;
  389.    }
  390.    return rc;
  391. }
  392. /*E*/
  393. /*F*/ PUBLIC UWORD updatespecialstats(GD gd, struct GlobalDevData *gdd)
  394. {
  395.    struct PublicDevData *pdd;
  396.    UWORD rc = 0;
  397.  
  398.    pdd = gdd->gd_Public;
  399.    pdd->pd_S2SpecialStats.RecordCountMax = NUM_SPECIALSTATS;
  400.    pdd->pd_S2Req.ios2_StatData = (void*)&pdd->pd_S2SpecialStats;
  401.    pdd->pd_S2Req.ios2_Req.io_Command = S2_GETSPECIALSTATS;
  402.    if (DoIO((struct IORequest*)&pdd->pd_S2Req))
  403.    {
  404.       struct Watch *w;
  405.  
  406.       SCANWATCHES(w, &gdd->gd_Watches)
  407.       {
  408.          if (w->w_Member == MEMBER_SPECIALSTATS)
  409.             w->w_Flags = (w->w_Flags & ~WF_ACTIVE) | WF_OFF;
  410.       }
  411.       rc = 1;
  412.    }
  413.    return rc;
  414. }
  415. /*E*/
  416. /*F*/ PUBLIC UWORD updatetracktype(GD gd, struct GlobalDevData *gdd)
  417. {
  418.    struct PublicDevData *pdd;
  419.    struct TrackType *tt;
  420.    ULONG i;
  421.    UWORD rc = 0;
  422.  
  423.    pdd = gdd->gd_Public;
  424.    for(i=gdd->gd_NumTT, tt=pdd->pd_TrackedTypes; i; --i, ++tt)
  425.    {
  426.       if (tt->tt_Flags & TTF_ACTIVE)
  427.       {
  428.          pdd->pd_S2Req.ios2_StatData = (void*)&tt->tt_Stats;
  429.          pdd->pd_S2Req.ios2_Req.io_Command = S2_GETTYPESTATS;
  430.          if (DoIO((struct IORequest*)&pdd->pd_S2Req))
  431.          {
  432.             struct Watch *w;
  433.  
  434.             SCANWATCHES(w, &gdd->gd_Watches)
  435.             {
  436.                if (w->w_TrackType == tt)
  437.                   w->w_Flags = (w->w_Flags & ~WF_ACTIVE) | WF_OFF;
  438.             }
  439.             rc = 1;
  440.          }
  441.       }
  442.    }
  443.    return rc;
  444. }
  445. /*E*/
  446.  
  447. /*F*/ PRIVATE LONG nextkey(STRPTR arg, STRPTR *next)
  448. {
  449.    STRPTR nx;
  450.    LONG len;
  451.  
  452.    if ((nx = strpbrk(arg, KEYDELIMITERS)) != NULL)
  453.    {
  454.       len = nx - arg;
  455.       ++nx;
  456.    }
  457.    else
  458.    {
  459.       len = strlen(arg);
  460.       nx = arg + len;
  461.    }
  462.  
  463.    *next = nx;
  464.    return len;
  465. }
  466. /*E*/
  467. /*F*/ PRIVATE BOOL nowparse(GD gd, LONG param[ARG_COUNT], BOOL *more, BOOL fromconfig)
  468. {
  469.    PD pd = gd->gd_Public;
  470.    struct GlobalDevData *gdd;
  471.    BOOL rc = TRUE;
  472.    LONG len;
  473.  
  474.    *more = FALSE;
  475.  
  476.    if (param[ARG_WINDOW])
  477.       strncpy((char*)pd->pd_Console, (char*)param[ARG_PUBSCREEN], sizeof(pd->pd_Console));
  478.  
  479.    if (param[ARG_LIST])
  480.    {
  481.       gd->gd_List = 1;
  482.    }
  483.    else
  484.    {
  485.       if (param[ARG_FROM])
  486.       {
  487.          if (gd->gd_ConfigName) freepvec(gd, gd->gd_ConfigName);
  488.          if (gd->gd_ConfigName = allocpvec(gd, strlen((char*)param[ARG_FROM])))
  489.          {
  490.             strcpy(gd->gd_ConfigName, (char*)param[ARG_FROM]);
  491.             *more = TRUE;
  492.          }
  493.          else rc = FALSE;
  494.       }
  495.  
  496.       /* DEVICE/A */
  497.       if (param[ARG_DEVICE])
  498.       {
  499.          if (gdd = makedevice(gd, (STRPTR)param[ARG_DEVICE]))
  500.          {
  501.             gdd->gd_FromConfig = fromconfig ? 1 : 0;
  502.  
  503.             /* UNIT/K/N */
  504.             if (param[ARG_UNIT])
  505.                gdd->gd_Unit = *(LONG*)param[ARG_UNIT];
  506.  
  507.             /* OFF/S */
  508.             gdd->gd_Active = (param[ARG_OFF] == 0);
  509.  
  510.             /* FORCE/S */
  511.             gdd->gd_Force = (param[ARG_FORCE] != 0);
  512.  
  513.             /* SHOW/K */
  514.             if (param[ARG_SHOW])
  515.             {
  516.                STRPTR arg, next;
  517.                struct Watch *w;
  518.  
  519.                SCANWATCHES(w, &gdd->gd_Watches)
  520.                {
  521.                   w->w_Flags &= ~WF_ACTIVE;
  522.                }
  523.                arg = (STRPTR)param[ARG_SHOW];
  524.                while(len = nextkey(arg, &next))
  525.                {
  526.                   SCANWATCHES(w, &gdd->gd_Watches)
  527.                   {
  528.                      if (!Strnicmp(w->w_Key, arg, len) || !Strnicmp(w->w_ShortKey, arg, len))
  529.                      {
  530.                         w->w_Flags |= WF_ACTIVE;
  531.                         break;
  532.                      }
  533.                   }
  534.                   arg = next;
  535.                }
  536.             }
  537.  
  538.             /* TRACKTYPE/K */
  539.             if (param[ARG_TRACKTYPE])
  540.             {
  541.                STRPTR arg, next;
  542.                WORD clen, i;
  543.                struct PublicDevData *pdd = gdd->gd_Public;
  544.  
  545.                arg = (STRPTR)param[ARG_TRACKTYPE];
  546.                while(len = nextkey(arg, &next))
  547.                {
  548.                   ++gdd->gd_NumTT;
  549.                   arg = next;
  550.                }
  551.  
  552.                if (pdd->pd_TrackedTypes = allocpvec(gd, gdd->gd_NumTT * sizeof(struct TrackType)))
  553.                {
  554.                   struct TrackType *tt = pdd->pd_TrackedTypes;
  555.                   STRPTR fmt;
  556.  
  557.                   arg = (STRPTR)param[ARG_TRACKTYPE];
  558.                   while(len = nextkey(arg, &next))
  559.                   {
  560.                      if (clen = strntolong(gd, arg, (LONG*)&tt->tt_Type, len))
  561.                      {
  562.                         tt->tt_Flags = 0;
  563.                         fmt = GetString(&gd->gd_LocaleInfo, TXT_TTLABEL);
  564.                         sprintf(tt->tt_Label, fmt, tt->tt_Type);
  565.                         sprintf(tt->tt_Key, "$%lx", tt->tt_Type);
  566.                         if (clen != len)
  567.                         {
  568.                            if (strchr(TTMASKSEPARATOR, arg[clen]) != NULL)
  569.                            {
  570.                               tt->tt_Flags |= TTF_INITIAL_SETUP;
  571.                               for(++clen, i=0; clen < len; ++clen, ++i)
  572.                               {
  573.                                  if (strchr(TTMASKACTIVE, arg[clen]) != NULL)
  574.                                     tt->tt_Flags |= ttmaskflags[i];
  575.                                  else if (strchr(TTMASKINACTIVE, arg[clen]) == NULL)
  576.                                  {
  577.                                     d(("bad ttmask char: %lc (%02lx)\n",arg[clen],arg[clen]));
  578.                                     rc = FALSE;
  579.                                     break;
  580.                                  }
  581.                               }
  582.                            }
  583.                         }
  584.                         ++tt;
  585.                      }
  586.                      else --gdd->gd_NumTT;
  587.  
  588.                      arg = next;
  589.                   }
  590.                }
  591.             }
  592.             AddTail((struct List*)&gd->gd_Devices, (struct Node*)gdd);
  593.             ++gd->gd_NumDevices;
  594.          }
  595.       }
  596.  
  597.       if (rc)
  598.       {
  599.          if (!gd->gd_HadRefresh && param[ARG_REFRESH])
  600.          {
  601.             gd->gd_Refresh = *(LONG*)(param[ARG_REFRESH]);
  602.             gd->gd_HadRefresh = 1;
  603.          }
  604.  
  605.          if (!gd->gd_HadFont && param[ARG_FONT])
  606.          {
  607.             gd->gd_CustomFont = 1;
  608.             strncpy(pd->pd_Fontname, (char*)param[ARG_FONT], sizeof(pd->pd_Fontname));
  609.             pd->pd_Font.tta_Name = (STRPTR)pd->pd_Fontname;
  610.             pd->pd_Font.tta_YSize = param[ARG_FONTSIZE] ? *(LONG*)(param[ARG_FONTSIZE]) : DEF_FONTSIZE;
  611.             pd->pd_Font.tta_Style = FS_NORMAL;
  612.             pd->pd_Font.tta_Flags = FPF_DISKFONT;
  613.             pd->pd_Font.tta_Tags = NULL;
  614.             gd->gd_HadFont = 1;
  615.          }
  616.  
  617.          if (!gd->gd_HadLeft && param[ARG_LEFT])
  618.          {
  619.             gd->gd_Left = *(LONG*)(param[ARG_LEFT]);
  620.             gd->gd_HadLeft = 1;
  621.          }
  622.  
  623.          if (!gd->gd_HadTop && param[ARG_TOP])
  624.          {
  625.             gd->gd_Top = *(LONG*)(param[ARG_TOP]);
  626.             gd->gd_HadTop = 1;
  627.          }
  628.  
  629.          if (!gd->gd_HadInactive && param[ARG_NOACTIVATE])
  630.          {
  631.             gd->gd_Inactive = 1;
  632.             gd->gd_HadInactive = 1;
  633.          }
  634.  
  635.          if (!gd->gd_HadWindowToBack && param[ARG_WINDOWTOBACK])
  636.          {
  637.             gd->gd_ToBack = 1;
  638.             gd->gd_HadWindowToBack = 1;
  639.          }
  640.  
  641.          if (!gd->gd_HadPubscreen && param[ARG_PUBSCREEN])
  642.          {
  643.             strncpy((char*)pd->pd_Pubscreen, (char*)param[ARG_PUBSCREEN],
  644.                                                    sizeof(pd->pd_Pubscreen));
  645.             gd->gd_HadPubscreen = 1;
  646.          }
  647.       }
  648.    }
  649.  
  650.    return rc;
  651. }
  652. /*E*/
  653. /*F*/ PRIVATE BOOL parseargs(GD gd)
  654. {
  655.    PD pd = gd->gd_Public;
  656.    BOOL rc = FALSE;
  657.    LONG param[ARG_COUNT];
  658.    BOOL more;
  659. #if (USE_EXTREADARGS != 0)
  660.    struct ExtRDArgs eargs = {NULL};
  661.  
  662.    eargs.erda_Window        = (STRPTR)DEF_CONSOLE;
  663.    eargs.erda_Template      = (STRPTR)TEMPLATE;
  664.    eargs.erda_Parameter     = param;
  665.    eargs.erda_FileParameter = -1;
  666.    eargs.erda_SysBase       = SysBase;
  667.    eargs.erda_DOSBase       = DOSBase;
  668.    eargs.erda_IconBase      = IconBase;
  669. #else
  670.    struct RDArgs *rda;
  671. #endif
  672.  
  673.    memset(param, '\0', sizeof(param));
  674.  
  675. #if (USE_EXTREADARGS != 0)
  676.    if (ExtReadArgs(gd->gd_argc, (STRPTR*)gd->gd_argv, &eargs) == 0)
  677. #else
  678.    if (rda = ReadArgs((STRPTR)TEMPLATE, param, NULL))
  679. #endif
  680.    {
  681.       /* some default values */
  682.       gd->gd_Refresh = DEF_REFRESH;
  683.       gd->gd_CustomFont = 0;
  684.       gd->gd_Top = DEF_TOP;
  685.       gd->gd_Left = DEF_LEFT;
  686.       strncpy((char*)pd->pd_Console, DEF_CONSOLE, sizeof(pd->pd_Console));
  687.  
  688.       rc = nowparse(gd, param, &more, FALSE);
  689.       if (rc && !gd->gd_List)
  690.       {
  691.          BPTR file;
  692.          struct RDArgs *mrda, *xrda;
  693.          STRPTR line;
  694.  
  695.          while(rc && more)
  696.          {
  697.             if (file = Open(gd->gd_ConfigName, MODE_OLDFILE))
  698.             {
  699.                if (line = allocpvec(gd, 1024))
  700.                {
  701.                   if (mrda = AllocDosObject(DOS_RDARGS, NULL))
  702.                   {
  703.                      while(FGets(file, line, 1024))
  704.                      {
  705.                         d(("line : <%s>\n",line));
  706.                         mrda->RDA_Source.CS_Buffer = line;
  707.                         mrda->RDA_Source.CS_Length = strlen(line);
  708.                         mrda->RDA_Source.CS_CurChr = 0;
  709.                         mrda->RDA_Flags |= RDAF_NOPROMPT;
  710.                         memset(param, '\0', sizeof(param));
  711.                         if (xrda = ReadArgs((STRPTR)TEMPLATE, param, mrda))
  712.                         {
  713.                            nowparse(gd, param, &more, TRUE);
  714.                            FreeArgs(xrda);
  715.                         }
  716.                         else break;
  717.                      }
  718.                      if (gd->gd_NumDevices == 0)
  719.                      {
  720.                         message(gd, REQ_ERROR_TITLE, REQ_ERROR_READARGS,
  721.                                                             REQ_ERROR_QUITBUTTON, IoErr());
  722.                         rc = FALSE;
  723.                      }
  724.                      FreeDosObject(DOS_RDARGS, mrda);
  725.                   }
  726.                   else
  727.                   {
  728.                      message(gd, REQ_ERROR_TITLE, REQ_ERROR_READARGS,
  729.                                                          REQ_ERROR_QUITBUTTON, IoErr());
  730.                      rc = FALSE;
  731.                   }
  732.                   freepvec(gd, line);
  733.                }
  734.                Close(file);
  735.             }
  736.             else
  737.             {
  738.                message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOCONFIG, REQ_ERROR_QUITBUTTON, gd->gd_ConfigName);
  739.                rc = FALSE;
  740.             }
  741.          }
  742.       }
  743.  
  744.       if (!gd->gd_List && IsListEmpty((struct List*)&gd->gd_Devices))
  745.       {
  746.          message(gd, REQ_ERROR_TITLE, REQ_ERROR_NODEVS, REQ_ERROR_QUITBUTTON);
  747.          rc = FALSE;
  748.       }
  749.  
  750. #if (USE_EXTREADARGS != 0)
  751.       ExtFreeArgs(&eargs);
  752. #else
  753.       FreeArgs(rda);
  754. #endif
  755.    }
  756.    else
  757.    {
  758.       if (gd->gd_CLI)
  759.          PrintFault(IoErr(),gd->gd_ProgramName);
  760.       else
  761.          message(gd, REQ_ERROR_TITLE, REQ_ERROR_READARGS,
  762.                                           REQ_ERROR_QUITBUTTON, IoErr());
  763.    }
  764.    return(rc);
  765. }
  766. /*E*/
  767. /*F*/ PRIVATE VOID openconsole(GD gd)
  768. {
  769.    struct PublicData *pd = gd->gd_Public;
  770.  
  771.    if (!gd->gd_CLI)
  772.    {
  773.       if (gd->gd_Output = Open(pd->pd_Console, MODE_OLDFILE))
  774.       {
  775.          gd->gd_OldConsoleTask = SetConsoleTask(((struct FileHandle*)BADDR(gd->gd_Output))->fh_Type);
  776.          gd->gd_OldOutput = SelectOutput(gd->gd_Output);
  777.          gd->gd_OutputSelected = 1;
  778.          gd->gd_CTSelected = 1;
  779.          if (gd->gd_Input = Open("*", MODE_OLDFILE))
  780.          {
  781.             gd->gd_OldInput = SelectInput(gd->gd_Input);
  782.             gd->gd_InputSelected = 1;
  783.          }
  784.          else d(("no input\n"));
  785.       }
  786.       else d(("no output\n"));
  787.    }
  788. }
  789. /*E*/
  790. /*F*/ PRIVATE VOID cleanup(GD gd)
  791. {
  792.    PD pd = gd->gd_Public;
  793.    struct GlobalDevData *gdd;
  794.  
  795.    closegui(gd);
  796.    if (pd && pd->pd_TReq.tr_node.io_Device) CloseDevice((struct IORequest*)&pd->pd_TReq);
  797.    SCANDEVS(gdd, &gd->gd_Devices)
  798.    {
  799.       struct PublicDevData *pdd = gdd->gd_Public;
  800.       struct TrackType *tt;
  801.       ULONG i;
  802.  
  803.       if (pdd->pd_S2Req.ios2_Req.io_Device)
  804.       {
  805.          for(i=gdd->gd_NumTT, tt=pdd->pd_TrackedTypes; i; --i, ++tt)
  806.          {
  807.             if (tt->tt_Flags & TTF_TRACKED)
  808.             {
  809.                pdd->pd_S2Req.ios2_PacketType = tt->tt_Type;
  810.                pdd->pd_S2Req.ios2_Req.io_Command = S2_UNTRACKTYPE;
  811.                DoIO((struct IORequest*)&pdd->pd_S2Req);
  812.             }
  813.          }
  814.          CloseDevice((struct IORequest*)&pdd->pd_S2Req);
  815.       }
  816.    }
  817.    if (gd->gd_S2Port) DeleteMsgPort(gd->gd_S2Port);
  818.    if (gd->gd_TPort) DeleteMsgPort(gd->gd_TPort);
  819.    if (gd->gd_LocaleInfo.li_Catalog) CloseCatalog(gd->gd_LocaleInfo.li_Catalog);
  820.    if (LocaleBase) CloseLibrary(LocaleBase);
  821.    if (GTLayoutBase) CloseLibrary(GTLayoutBase);
  822.    if (GadToolsBase) CloseLibrary(GadToolsBase);
  823.    if (UtilityBase) CloseLibrary(UtilityBase);
  824.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  825.    if (gd->gd_InputSelected) SelectInput(gd->gd_OldInput);
  826.    if (gd->gd_OutputSelected) SelectOutput(gd->gd_OldOutput);
  827.    if (gd->gd_CTSelected) SetConsoleTask(gd->gd_OldConsoleTask);
  828.    if (gd->gd_Input) Close(gd->gd_Input);
  829.    if (gd->gd_Output) Close(gd->gd_Output);
  830.    if (DOSBase) CloseLibrary(DOSBase);
  831.    if (gd->gd_Public) FreeVec(gd->gd_Public);
  832.    if (gd->gd_PubPool) AsmDeletePool(gd->gd_PubPool, (struct ExecBase*)SysBase);
  833.    if (gd->gd_AnyPool) AsmDeletePool(gd->gd_AnyPool, (struct ExecBase*)SysBase);
  834.    FreeVec(gd);
  835.    return ;
  836. }
  837. /*E*/
  838. /*F*/ PRIVATE VOID dummys2copy(VOID) {}
  839. /*E*/
  840. /*F*/ PRIVATE BOOL opendevs(GD gd)
  841. {
  842.    PD  pd = gd->gd_Public;
  843.    struct GlobalDevData *gdd;
  844.    struct PublicDevData *pdd;
  845.    BOOL rc = FALSE;
  846.    struct TrackType *tt;
  847.    ULONG i;
  848.    static const struct TagItem dummybuffermgnt[] =
  849.    {
  850.       S2_CopyToBuff, (ULONG)&dummys2copy,
  851.       S2_CopyFromBuff, (ULONG)&dummys2copy,
  852.       TAG_DONE
  853.    };
  854.  
  855.    gd->gd_We = FindTask(NULL);
  856.  
  857.    if (gd->gd_TPort = CreateMsgPort())
  858.    {
  859.       pd->pd_TReq.tr_node.io_Message.mn_ReplyPort = gd->gd_TPort;
  860.       if (!OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest*)&pd->pd_TReq, 0L))
  861.       {
  862.          pd->pd_TReq.tr_node.io_Command = TR_ADDREQUEST;
  863.          gd->gd_time.tv_secs = gd->gd_Refresh;
  864.          gd->gd_time.tv_micro = 0;
  865.          gd->gd_TimerOff = 1;
  866.  
  867.          rc = TRUE;
  868.  
  869.          if (gd->gd_S2Port = CreateMsgPort())
  870.          {
  871.             SCANDEVS(gdd, &gd->gd_Devices)
  872.             {
  873.                pdd = gdd->gd_Public;
  874.  
  875.                sprintf(gdd->gd_Title, "%s/%ld", FilePart(gdd->gd_Device), gdd->gd_Unit);
  876.  
  877.                pdd->pd_S2Req.ios2_Req.io_Message.mn_ReplyPort = gd->gd_S2Port;
  878.                if (gdd->gd_Force)
  879.                   pdd->pd_S2Req.ios2_BufferManagement = (VOID*)dummybuffermgnt;
  880.  
  881.                if (!OpenDevice(gdd->gd_Device, gdd->gd_Unit, (struct IORequest*)&pdd->pd_S2Req, 0L))
  882.                {
  883.                   pdd->pd_S2DeviceQuery.SizeAvailable = sizeof(pdd->pd_S2DeviceQuery);
  884.                   pdd->pd_S2Req.ios2_StatData = &pdd->pd_S2DeviceQuery;
  885.                   pdd->pd_S2Req.ios2_Req.io_Command = S2_DEVICEQUERY;
  886.                   d(("S2_DEVICEQUERY\n"));
  887.                   if (DoIO((struct IORequest*)&pdd->pd_S2Req) == 0)
  888.                   {
  889.                      for(i=gdd->gd_NumTT, tt=pdd->pd_TrackedTypes; i; --i, ++tt)
  890.                      {
  891.                         pdd->pd_S2Req.ios2_PacketType = tt->tt_Type;
  892.                         pdd->pd_S2Req.ios2_Req.io_Command = S2_TRACKTYPE;
  893.                         d(("S2_TRACKTYPE %ld\n", tt->tt_Type));
  894.                         if (DoIO((struct IORequest*)&pdd->pd_S2Req) == 0)
  895.                         {
  896.                            tt->tt_Flags |= TTF_TRACKED;
  897.                         }
  898.                         else if ((pdd->pd_S2Req.ios2_Req.io_Error == S2ERR_BAD_STATE) &&
  899.                                  (pdd->pd_S2Req.ios2_WireError == S2WERR_ALREADY_TRACKED))
  900.                         {
  901.                            tt->tt_Flags &= ~TTF_TRACKED;
  902.                         }
  903.                         else
  904.                         {
  905.                            message(gd, REQ_ERROR_TITLE, REQ_ERROR_TRACK, REQ_ERROR_QUITBUTTON,
  906.                                              pdd->pd_S2Req.ios2_PacketType,
  907.                                              pdd->pd_S2Req.ios2_Req.io_Error,
  908.                                              pdd->pd_S2Req.ios2_WireError);
  909.                            rc = FALSE;
  910.                            break;
  911.                         }
  912.                      }
  913.                   }
  914.                   else
  915.                   {
  916.                      message(gd, REQ_ERROR_TITLE, REQ_ERROR_QUERY, REQ_ERROR_QUITBUTTON,
  917.                                              gdd->gd_Device, gdd->gd_Unit);
  918.                      rc = FALSE;
  919.                   }
  920.                }
  921.                else
  922.                {
  923.                   message(gd, REQ_ERROR_TITLE, REQ_ERROR_OPENDEV, REQ_ERROR_QUITBUTTON,
  924.                                              gdd->gd_Device, gdd->gd_Unit);
  925.                   rc = FALSE;
  926.                }
  927.                if (!rc) break;
  928.             }
  929.          }
  930.          else message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOMSGPORT, REQ_ERROR_QUITBUTTON);
  931.       }
  932.       else message(gd, REQ_ERROR_TITLE, REQ_ERROR_OPENDEV, REQ_ERROR_QUITBUTTON,
  933.                               TIMERNAME, UNIT_VBLANK);
  934.    }
  935.    else message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOMSGPORT, REQ_ERROR_QUITBUTTON);
  936.  
  937.    return rc;
  938. }
  939. /*E*/
  940. /*F*/ PRIVATE GD createenv(ULONG argc, UBYTE **argv)
  941. {
  942.    GD gd, new;
  943.    BOOL ok = FALSE;
  944.  
  945.    {
  946.       LOCALSYSBASE;
  947.       new = AllocVec(sizeof(struct GlobalData), MEMF_ANY | MEMF_CLEAR);
  948.       new->gd_SysBase = SysBase;
  949.    }
  950.  
  951.    if (gd = new)
  952.    {
  953.       gd->gd_argv = argv;
  954.       gd->gd_argc = argc;
  955.       NewList((struct List*)&gd->gd_Devices);
  956.       if (gd->gd_Public = AllocVec(sizeof(struct PublicData) +
  957.              (NUM_SPECIALSTATS-1)*sizeof(struct Sana2SpecialStatRecord),
  958.                                             MEMF_PUBLIC | MEMF_CLEAR))
  959.       {
  960.          if (DOSBase = openlib(gd, "dos.library", 37))
  961.          {
  962.             if (LocaleBase = openlib(gd, "locale.library", 38))
  963.                gd->gd_LocaleInfo.li_Catalog = OpenCatalog(NULL, "sana2meter.catalog",
  964.                                                                OC_Version, CATALOG_VERSION, TAG_DONE);
  965.  
  966.             if (UtilityBase = openlib(gd, "utility.library", 37))
  967.             {
  968.                if (IntuitionBase = openlib(gd, "intuition.library", 37))
  969.                {
  970.                   if (GadToolsBase = openlib(gd, "gadtools.library", 37))
  971.                   {
  972.                      if (GTLayoutBase = openlib(gd, "gtlayout.library", 24))
  973.                      {
  974.                         GetProgramName(new->gd_ProgramName, sizeof(new->gd_ProgramName));
  975.  
  976.                         if (!(gd->gd_CLI = (Cli() != NULL)))
  977.                            IconBase = openlib(gd, "icon.library", 0);
  978.  
  979.                         if (gd->gd_AnyPool = AsmCreatePool(ANYPOOLKIND, ANYPOOLPUDDLE, ANYPOOLTHRESH,
  980.                                                       (struct ExecBase*)SysBase))
  981.                         {
  982.                            if (gd->gd_PubPool = AsmCreatePool(PUBPOOLKIND, PUBPOOLPUDDLE, PUBPOOLTHRESH,
  983.                                                          (struct ExecBase*)SysBase))
  984.                            {
  985.                               if (parseargs(gd))
  986.                               {
  987.                                  if (preparetts(gd))
  988.                                  {
  989.                                     openconsole(gd);
  990.                                     ok = TRUE;
  991.                                  }
  992.                               }
  993.                            }
  994.                            else message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOPOOL, REQ_ERROR_QUITBUTTON);
  995.                         }
  996.                         else message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOPOOL, REQ_ERROR_QUITBUTTON);
  997.                      }
  998.                   }
  999.                }
  1000.             }
  1001.          }
  1002.          else d(("no dos.library\n"));
  1003.       }
  1004.       else d(("out of memory\n"));
  1005.    }
  1006.    else d(("out of memory\n"));
  1007.  
  1008.    if (!ok && new)
  1009.    {
  1010.       cleanup(new);
  1011.       new = NULL;
  1012.    }
  1013.    return new;
  1014. }
  1015. /*E*/
  1016.  
  1017. /*F*/PUBLIC VOID saveconfig(GD gd)
  1018. {
  1019. #define MAXTOOLTYPE 2048
  1020.    BPTR old, new, cfgfile = 0;
  1021.    struct DiskObject *dob;
  1022.    STRPTR tooltype;
  1023.    STRPTR progname;
  1024.    struct GlobalDevData *gdd;
  1025.  
  1026.    if (!IconBase)
  1027.       IconBase = openlib(gd, "icon.library", 0);
  1028.  
  1029.    if (IconBase)
  1030.    {
  1031.       if (gd->gd_CLI)
  1032.       {
  1033.          progname = gd->gd_ProgramName;
  1034.          new = Lock("PROGDIR:", ACCESS_READ);
  1035.       }
  1036.       else
  1037.       {
  1038.          struct WBArg *wbarg = ((struct WBStartup *)gd->gd_argv)->sm_ArgList;
  1039.          progname = wbarg->wa_Name;
  1040.          new = DupLock(wbarg->wa_Lock);
  1041.       }
  1042.  
  1043.       if(new)
  1044.       {
  1045.          old = CurrentDir(new);
  1046.          if (dob = GetDiskObject(progname))
  1047.          {
  1048.             if (tooltype = allocpvec(gd, MAXTOOLTYPE))
  1049.             {
  1050.                SCANDEVS(gdd, &gd->gd_Devices)
  1051.                {
  1052.                   if (gdd->gd_FromConfig)
  1053.                   {
  1054.                      if (!cfgfile) cfgfile = Open(gd->gd_ConfigName, MODE_NEWFILE);
  1055.                      if (cfgfile)
  1056.                      {
  1057.                         sprintf(tooltype, "DEVICE=%s UNIT=%ld%s%s",
  1058.                                        gdd->gd_Device,
  1059.                                        gdd->gd_Unit,
  1060.                                        gdd->gd_Force ? " FORCE" : "",
  1061.                                        gdd->gd_Active ? "" : " OFF");
  1062.  
  1063.                         strcat(tooltype, " SHOW=");
  1064.                         {
  1065.                            struct Watch *w;
  1066.                            BOOL first = TRUE;
  1067.  
  1068.                            SCANWATCHES(w, &gdd->gd_Watches)
  1069.                            {
  1070.                               if ((w->w_Member != MEMBER_TRACKTYPE) && (w->w_Flags & WF_ACTIVE) && w->w_Key)
  1071.                               {
  1072.                                  if (first)
  1073.                                     first = FALSE;
  1074.                                  else
  1075.                                     strcat(tooltype, ",");
  1076.                                  strcat(tooltype, w->w_Key);
  1077.                               }
  1078.                            }
  1079.                         }
  1080.                         if (gdd->gd_NumTT)
  1081.                         {
  1082.                            strcat(tooltype, " TRACKTYPE=");
  1083.                            {
  1084.                               struct Watch *w;
  1085.                               BOOL first = TRUE;
  1086.  
  1087.                               SCANWATCHES(w, &gdd->gd_Watches)
  1088.                               {
  1089.                                  if (w->w_Member == MEMBER_TRACKTYPE)
  1090.                                  {
  1091.                                     if (w->w_Key)
  1092.                                     {
  1093.                                        if (first)
  1094.                                           first = FALSE;
  1095.                                        else
  1096.                                           strcat(tooltype, ",");
  1097.  
  1098.                                        sprintf(&tooltype[strlen(tooltype)], "%s%lc",
  1099.                                              w->w_Key, (LONG)TTMASKSEPARATOR[0]);
  1100.                                     }
  1101.                                     sprintf(&tooltype[strlen(tooltype)], "%lc",
  1102.                                        (w->w_Flags & WF_ACTIVE) ? TTMASKACTIVE[0] : TTMASKINACTIVE[0]);
  1103.                                  }
  1104.                               }
  1105.                            }
  1106.                         }
  1107.                         strcat(tooltype, "\n");
  1108.                         Write(cfgfile, tooltype, strlen(tooltype));
  1109.                      }
  1110.                      else
  1111.                      {
  1112.                         message(gd, REQ_ERROR_TITLE, REQ_ERROR_NOCONFIG,
  1113.                                                       REQ_ERROR_QUITBUTTON, gd->gd_ConfigName);
  1114.                      }
  1115.                   }
  1116.                   else
  1117.                   {
  1118.                      /* DEVICE, UNIT */
  1119.                      sprintf(tooltype, "DEVICE=%s", gdd->gd_Device);
  1120.                      AddToolType(gd, dob, tooltype);
  1121.  
  1122.                      sprintf(tooltype, "UNIT=%ld", gdd->gd_Unit);
  1123.                      AddToolType(gd, dob, tooltype);
  1124.  
  1125.                      sprintf(tooltype, "%sFORCE%s",
  1126.                                  gdd->gd_Force ? "(" : "", gdd->gd_Force ? ")" : "");
  1127.                      AddToolType(gd, dob, tooltype);
  1128.  
  1129.                      sprintf(tooltype, "%sOFF%s",
  1130.                                  gdd->gd_Active ? "(" : "", gdd->gd_Active ? ")" : "");
  1131.                      AddToolType(gd, dob, tooltype);
  1132.  
  1133.                         /* SHOW watches */
  1134.                      strcpy(tooltype, "SHOW=");
  1135.                      {
  1136.                         struct Watch *w;
  1137.                         BOOL first = TRUE;
  1138.  
  1139.                         SCANWATCHES(w, &gdd->gd_Watches)
  1140.                         {
  1141.                            if ((w->w_Member != MEMBER_TRACKTYPE) && (w->w_Flags & WF_ACTIVE) && w->w_Key)
  1142.                            {
  1143.                               if (first)
  1144.                                  first = FALSE;
  1145.                               else
  1146.                                  strcat(tooltype, ",");
  1147.                               strcat(tooltype, w->w_Key);
  1148.                            }
  1149.                         }
  1150.                      }
  1151.                      AddToolType(gd, dob, tooltype);
  1152.  
  1153.                      /* TRACKTYPE watches */
  1154.                      strcpy(tooltype, "TRACKTYPE=");
  1155.                      {
  1156.                         struct Watch *w;
  1157.                         BOOL first = TRUE;
  1158.  
  1159.                         SCANWATCHES(w, &gdd->gd_Watches)
  1160.                         {
  1161.                            if (w->w_Member == MEMBER_TRACKTYPE)
  1162.                            {
  1163.                               if (w->w_Key)
  1164.                               {
  1165.                                  if (first)
  1166.                                     first = FALSE;
  1167.                                  else
  1168.                                     strcat(tooltype, ",");
  1169.  
  1170.                                  sprintf(&tooltype[strlen(tooltype)], "%s%lc",
  1171.                                        w->w_Key, (LONG)TTMASKSEPARATOR[0]);
  1172.                               }
  1173.                               sprintf(&tooltype[strlen(tooltype)], "%lc",
  1174.                                  (w->w_Flags & WF_ACTIVE) ? TTMASKACTIVE[0] : TTMASKINACTIVE[0]);
  1175.                            }
  1176.                         }
  1177.                         if (first)
  1178.                            strcpy(tooltype, "(TRACKTYPE=)");
  1179.                      }
  1180.                      AddToolType(gd, dob, tooltype);
  1181.  
  1182.                      if (gd->gd_ConfigName)
  1183.                         sprintf(tooltype, "FROM=%s", gd->gd_ConfigName);
  1184.                      else
  1185.                         strcpy(tooltype, "(FROM=)");
  1186.                      AddToolType(gd, dob, tooltype);
  1187.                   }
  1188.                }
  1189.                if (cfgfile) Close(cfgfile);
  1190.  
  1191.                /* window position */
  1192.                sprintf(tooltype, "LEFT=%ld", gd->gd_Handle->Window->LeftEdge);
  1193.                AddToolType(gd, dob, tooltype);
  1194.                sprintf(tooltype, "TOP=%ld", gd->gd_Handle->Window->TopEdge);
  1195.                AddToolType(gd, dob, tooltype);
  1196.  
  1197.                /* refresh interval */
  1198.                sprintf(tooltype, "REFRESH=%ld", gd->gd_Refresh);
  1199.                AddToolType(gd, dob, tooltype);
  1200.  
  1201.                freepvec(gd, tooltype);
  1202.             }
  1203.             PutDiskObject(progname, dob);
  1204.          }
  1205.          UnLock(CurrentDir(old));
  1206.       }
  1207.       CloseLibrary(IconBase);
  1208.    }
  1209.  
  1210.    return ;
  1211. }
  1212. /*E*/
  1213.  
  1214. /*F*/ PUBLIC VOID SAVEDS STDARGS main(ULONG argc, UBYTE **argv)
  1215. {
  1216.    int rc = RETURN_FAIL;
  1217.    ULONG m_wait, m_tport, m_s2port, m_recv, m_window;
  1218.    BOOL running;
  1219.    GD gd;
  1220.    PD pd;
  1221.  
  1222.    if (!(gd = createenv(argc, argv))) goto leave;
  1223.    pd = gd->gd_Public;
  1224.  
  1225.    if (gd->gd_List)
  1226.    {
  1227.       const struct NewWatch *nw;
  1228.       Printf("\033[1mTable of keywords (abbrev'd form in parenthesis):\033[0m\n");
  1229.       for (nw = stdwatches; nw->nw_Member != MEMBER_NONE; nw++)
  1230.          Printf("%s (%s)\n", nw->nw_Key, nw->nw_ShortKey);
  1231.       rc = RETURN_OK;
  1232.       goto leave;
  1233.    }
  1234.  
  1235.    if (!opendevs(gd)) goto leave;
  1236.  
  1237.    {
  1238.       struct GlobalDevData *gdd;
  1239.       UWORD fail;
  1240.  
  1241.       SCANDEVS(gdd, &gd->gd_Devices)
  1242.       {
  1243.          updateupdate(gd, gdd);
  1244.          fail = updateglobalstats(gd, gdd);
  1245.          fail += updatespecialstats(gd, gdd);
  1246.          fail += updatetracktype(gd, gdd);
  1247.          if (fail)
  1248.          {
  1249.             updateupdate(gd, gdd);
  1250.             updateglobalstats(gd, gdd);
  1251.             updatespecialstats(gd, gdd);
  1252.             updatetracktype(gd, gdd);
  1253.          }
  1254.       }
  1255.       updateactives(gd);
  1256.    }
  1257.    getspeciallabels(gd);
  1258.  
  1259.    if (!preparemenu(gd)) goto leave;
  1260.  
  1261.    if (!opengui(gd)) goto leave;
  1262.  
  1263.    updategui(gd, TRUE);
  1264.  
  1265.    m_wait = SIGBREAKF_CTRL_C |
  1266.             (m_tport = 1 << gd->gd_TPort->mp_SigBit) |
  1267.             (m_s2port = 1 << gd->gd_S2Port->mp_SigBit) |
  1268.             (m_window = 1 << gd->gd_Handle->Window->UserPort->mp_SigBit);
  1269.  
  1270.    if (gd->gd_NeedTimer)
  1271.    {
  1272.       d(("starting timer\n"));
  1273.       pd->pd_TReq.tr_time = gd->gd_time;
  1274.       SendIO((struct IORequest*)&pd->pd_TReq);
  1275.       gd->gd_TimerOff = 0;
  1276.    }
  1277.  
  1278.    rc = RETURN_OK;
  1279.    for(running = TRUE; running;)
  1280.    {
  1281.       d(("Wait()\n"));
  1282.       m_recv = Wait(m_wait);
  1283.  
  1284.       if (m_recv & SIGBREAKF_CTRL_C)
  1285.       {
  1286.          running = FALSE;
  1287.       }
  1288.  
  1289.       if (m_recv & m_window)
  1290.       {
  1291.          BOOL update = FALSE;
  1292.  
  1293.          running = dowindow(gd, &update);
  1294.          if (running && update)
  1295.          {
  1296.             struct GlobalDevData *gdd;
  1297.             UWORD fail;
  1298.  
  1299.             if (!gd->gd_TimerOff)
  1300.                AbortIO((struct IORequest*)&pd->pd_TReq);
  1301.  
  1302.             closegui(gd);
  1303.             SCANDEVS(gdd, &gd->gd_Devices)
  1304.             {
  1305.                fail = 0;
  1306.                updateupdate(gd, gdd);
  1307.                if (gdd->gd_GetGlobalStats) fail = updateglobalstats(gd, gdd);
  1308.                if (gdd->gd_GetSpecialStats) fail += updatespecialstats(gd, gdd);
  1309.                if (gdd->gd_GetTrackType) fail += updatetracktype(gd, gdd);
  1310.                if (fail) updateupdate(gd, gdd);
  1311.                /* rh(c)slip seems to leave a DoIO() with the port bit set */
  1312.                SetSignal(0, m_s2port);
  1313.             }
  1314.             updateactives(gd);
  1315.             if (!opengui(gd)) running = FALSE;
  1316.  
  1317.             if (gd->gd_NeedTimer && gd->gd_TimerOff)
  1318.             {
  1319.                d(("starting timer\n"));
  1320.                pd->pd_TReq.tr_time = gd->gd_time;
  1321.                SendIO((struct IORequest*)&pd->pd_TReq);
  1322.                gd->gd_TimerOff = 0;
  1323.             }
  1324.          }
  1325.       }
  1326.  
  1327.       if (m_recv & m_s2port)
  1328.       {
  1329.          d(("spurious signal from SANA2 MsgPort (mask = %08lx)\n", m_recv));
  1330.       }
  1331.  
  1332.       if (m_recv & m_tport)
  1333.       {
  1334.          struct GlobalDevData *gdd;
  1335.          UWORD fail = 0;
  1336.  
  1337.          if (!gd->gd_TimerOff)
  1338.             WaitIO((struct IORequest*)&pd->pd_TReq);
  1339.  
  1340.          if (gd->gd_NumActives)
  1341.          {
  1342.             SCANDEVS(gdd, &gd->gd_Devices)
  1343.             {
  1344.                if (gdd->gd_GetGlobalStats) fail = updateglobalstats(gd, gdd);
  1345.                if (gdd->gd_GetSpecialStats) fail += updatespecialstats(gd, gdd);
  1346.                if (gdd->gd_GetTrackType) fail += updatetracktype(gd, gdd);
  1347.                /* rh(c)slip seems to leave a DoIO() with the port bit set */
  1348.                SetSignal(0, m_s2port);
  1349.             }
  1350.             if (fail)
  1351.             {
  1352.                closegui(gd);
  1353.                updateupdate(gd, gdd);
  1354.                updateactives(gd);
  1355.                if (!opengui(gd)) running = FALSE;
  1356.             }
  1357.             else
  1358.                updategui(gd, FALSE);
  1359.             if (gd->gd_NeedTimer)
  1360.             {
  1361.                d(("starting timer\n"));
  1362.                pd->pd_TReq.tr_time = gd->gd_time;
  1363.                SendIO((struct IORequest*)&pd->pd_TReq);
  1364.             }
  1365.             else gd->gd_TimerOff = 1;
  1366.          }
  1367.          else gd->gd_TimerOff = 1;
  1368.       }
  1369.    }
  1370.  
  1371.    AbortIO((struct IORequest*)&pd->pd_TReq);
  1372.    WaitIO((struct IORequest*)&pd->pd_TReq);
  1373.  
  1374. leave:
  1375.    if (gd) cleanup(gd);
  1376.  
  1377.    exit(rc);
  1378.    return ;
  1379. }
  1380. /*E*/
  1381.  
  1382.